package com.tedu.API.io;

import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;
import org.junit.Test;

import java.io.*;

/**
 * 标准的IO流-----目的：数据传输  输出文本、图片
 * Java定义一套标准流-->数据传输-->创建流：直接创建某个流对象
 * 标准流划分①：方向划分  输入流和输出流
 *      输入流：读入--->文件--->相对于程序--->文件往程序走
 *      InputStream(抽象类：定义所有读的写法)【学习：子实现类】
 *      输出流：写出--->文件--->相对于程序--->程序写出
 *      OutputStream(抽象类：定义所有写的方法)【学习：子实现类】
 *          ②：功能划分
 *   ---->  低级流【节点流】：是建立在程序员与数据源之间的”管道“
 *               功能：负责搬运的数据流，输入流于输出流都有自己的低级流
 *               特点：一个字节一个字节读或者写的方法
 *          FileOutputStream  低级流继承InputStream---文件输出流：写
 *          FileInputStream   低级流继承OutputStream---文件输入流：读
 *          高级流【处理流】：不能直接创建对象，不能独立存在
 *                  功能：专门处理低级流以及其他高级流的流
 *                  特点：搬运数据时，实现具体功能：效率提高流
 *
 * ---总结：输入流和输出流，具备功能：低级流与高级流，
 *实际使用：明确使用具体流，每个流都有自己的功能
 *
 */
public class IOAPI {
    /**                                         文件输入流
     *               输入流             低级流---
     * 标准流   方向                功能：         文件输出流：FileOutputStream
     *               输出流             高级流
     *需求：写出一个文件 fos.txt
     *
     * FileOutputStream 构造器使用
     * new FileOutputStream(“路径+文件全称”)
     * new FileOutputStream("路径+文件全称",boolean append)
     * 写文件的同时实现追加效果，第二个参数：true  追加
     *                                false  默认不追加
     * new FileOutputStream(File file,boolean append)
     * 写出文件，采用File传入路径+全称
     */
    @Test
    public void testFOS()  {
//        RandomAccessFile raf=new RandomAccessFile("fos.txt","rw");
        try {
            //低级流---文件输出流对象---从程序中写出“文件：数据”
            FileOutputStream fos=new FileOutputStream("fos.txt",true);
            //需求：fos.txt  增加一行文本，每次运行实现追加效果
            String say="独one无two";  //字符串由字符数组构成--数组的功能getBytes()转换为字节数组
            //输出流---写功能：write(byte[] b)  写出字节数组
            fos.write(say.getBytes());
            //关闭流--目的：节省内存开销
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        }
    }
    /**
     * 文件输入流：读入操作
     * FileInputStream 文件输入流
     * read() 返回一个读取一个字节---效率低
     * read(字节数组byte[] b)  返回一个“指定字节数组：空间大小”的读取---效率高  √
     * 需求：读入fos.txt文件内容
     */
    @Test
    public void testFIS() {
        try {
            //创建文件输入流---读入：fos.txt
            FileInputStream fis=new FileInputStream("fos.txt");
            //读入效率高：创建字节数组-指定空间为：10KB
            byte[] data=new byte[1024*10];
            //读入操作：read(字节数组)  |  以10KB读入数据
            int len=fis.read(data);
            //写出：文本---字符串---针对流操作，提供构造器
            //                   文件按照“指定字节数组空间”写入程序中
            //                   从0开始写入程序，写入到-1结束
            //                   len:十进制转换为二进制，写入，不等于-1，一直写入
            //一次性将给定数据按照字节数组指定空间大小，写出成字符串
            String str=new String(data,0,len);
            System.out.println("打印Fos.txt文件:"+str);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        }
    }
    /**
     * 需求：利用标准流实现视频复制和粘贴
     */
    @Test
    public void testCV()  {
        try {
            //1.从"视频.mp4"复制 操作---读入
            FileInputStream fis=new FileInputStream("视频.mp4");
            //2.创建新文件“新文件.mp4"粘贴 操作---写出
            FileOutputStream fos=new FileOutputStream("新文件.mp4");
            //3.保存每次读取的数据【字节量--int】
            int len=-1;
            //4.一直 从"视频.mp4" 进行读入操作，不等于-1  一直读
            //(len=fis.read())!=-1
            while((len=fis.read())!=-1){//true
                //4.1同时写出“新文件.mp4”
                fos.write(len);
            }
            //5.关闭流   ---测：效率低---正常播放
            fis.close();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        }
    }
    /**
     * 需求：利用标准流实现视频复制粘贴---效率低
     *                              效率高--->空间执行为：自定  100KB
     *
     * 【高级流】BufferedInputStream   缓冲输入流---提升效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *         BufferedOutputStream  缓冲输出流---提高效率--缓冲区：字节数组【长度按照文件大小合理分配】
     *  高级流使用方式：①处理低级流，套在低级流上
     *               写法： new 高级流(传入低级流引用)
     *               ②直接使用高级流方法
     *               ③高级流不能直接创建【不能独立存在】
     */
    @Test
    public void testCVS()  {
        try {
            //1.创建低级流：读入”视频.mp4“
            FileInputStream fis=new FileInputStream("视频.mp4");
            //1.创建高级流：套在低级流上【自带缓冲区：字节数组】
            BufferedInputStream bis=new BufferedInputStream(fis);

            //2.创建低级流：写出“高效视频2.mp4”
            FileOutputStream fos=new FileOutputStream("高效视频2.mp4");
            //2.创建高级流：套在低级流上【自带缓冲带：字节数组】
            BufferedOutputStream bos=new BufferedOutputStream(fos);

            //3.保存数据
            int len=-1;
            //4.高级流--低级流方法一致-----read()读取内嵌缓冲区【字节数组】
            //  高级流--低级流方法一致-----write()写出内嵌缓冲区{【字节数组】
            //一直从“视频.mp4” 读取视频,不等于-1，一直读
            //(len=bis.read())!=-1
            long start=System.currentTimeMillis();  //系统时间毫秒数
            while ((len=bis.read())!=-1){
                bos.write(len);
            }
            long end=System.currentTimeMillis();
            System.out.println("缓冲区【自带缓冲区】："+(end-start)+"毫秒");
            //关闭流---高级流与低级流：都关--->高级流间接性关闭低级流--->关闭高级流
            bis.close();//高级流---缓冲输入流
            bos.close();//高级流---缓冲输出流
//        fis.close();//低级流---文件输入流
//        fos.close();//低级流---文件输出流
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
        }
    }
    /**
     * 高级流----缓冲流【内嵌缓冲区】
     * BufferedOutputStream   缓冲输出流
     *
     * 需求：通过缓冲输出流实现从程序写出文件：bos.txt,写出内容
     */
    @Test
    public void testBOS()  {
        try {
            //1.创建低级流--->bos.txt
            FileOutputStream fos=new FileOutputStream("bos.txt");
            //2.创建高级流--->缓冲区：字节数组--合理【传输效率】
            BufferedOutputStream bos=new BufferedOutputStream(fos);
            //3.写出文本内容
            String str="50块钱设计的再好看，也不如100块钱招人稀罕~~";
            //4.写出到bos.txt文件中:字符串转为字节数组--写出
            bos.write(str.getBytes());
            //5.将缓冲区的数据一次性写出   flush()
//        bos.flush();
            bos.close();    //关闭流---一定会把缓冲区数据全部写出
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        } finally {
        }
    }
    /**
     * 标准IO---成对【低级流+高级流】结合异常---数据传输---成功【异常需要捕获】
     * 需求：重构testBOS() 单元测试
     */
    @Test
    public void testBOSIO(){
        //1.置空流---提升所有流的作用域：使用范围
        FileOutputStream fos=null;//低级流：搬运数据
        BufferedOutputStream bos=null;//高级流：缓冲输出流
        //2.捕获流异常并且做出处理
        try {
            fos=new FileOutputStream("bos.txt");//低级流
            bos=new BufferedOutputStream(fos);//高级流：缓冲区：字节数组
            bos.write("独一无二".getBytes());
            bos.flush();
        } catch (FileNotFoundException e) {//IO流 “小” 异常
            e.printStackTrace();
        }catch (IOException e){//IO流“中” 异常：小异常父类
            e.printStackTrace();
        }catch (Exception e){//“大” 异常 Exception
            e.printStackTrace();
        } finally {
        }
    }

}
